package com.hee.erp.filter;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.Claim;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.hee.erp.common.R;
import com.hee.erp.constant.Const;
import com.hee.erp.constant.ReturnCode;
import com.hee.erp.modules.service.ISysUserService;
import com.hee.erp.pojo.LoginInfo;
import com.hee.erp.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;

@Slf4j
@WebFilter(filterName = "jwtFilter",urlPatterns = "/modules/*")
public class JwtFilter implements Filter {

    @Autowired
    ISysUserService sysUserService;

    private HashSet<String> excludesURIs = new HashSet<>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        excludesURIs.add("/api/modules/sysUser/login");
        excludesURIs.add("/api/modules/sysUser2/login");
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;

        final String token = request.getHeader(Const.REQUEST_HEADER_TOKEN);
        final String requestURI = request.getRequestURI();
        if("OPTIONS".equals(request.getMethod())){
            response.setStatus(HttpServletResponse.SC_OK);
            response.getWriter().println("ok");
            return;
        }

        if(!this.excludesURIs.contains(requestURI)){
            //必须要传入token的路径
            if(StringUtils.isBlank(token)){
                //未登录
                response.setContentType("application/json;charset=UTF-8");
                R<Object> result = R.fail(ReturnCode.RC402.getCode(), ReturnCode.RC402.getMsg());
                String strResult = JSONObject.toJSONString(result);
                response.getWriter().write(strResult);
                return;
            }
            Map<String, Claim> jwtInfo = JwtUtil.verifyToken(token);
            if(jwtInfo == null){
                //登录过期
                response.setContentType("application/json;charset=UTF-8");
                R<Object> result = R.fail(ReturnCode.RC403.getCode(), ReturnCode.RC403.getMsg());
                String strResult = JSONObject.toJSONString(result);
                response.getWriter().write(strResult);
                return;
            }
            String userId = jwtInfo.get("userId").asString();
            String userDbKey = jwtInfo.get("userDbKey").asString();
            Long expireTimeMillis = jwtInfo.get("expireTimeMillis").asLong();

            //保存登录信息到本地线程
            LoginInfo loginInfo = new LoginInfo();
            loginInfo.setUserId(userId);
            loginInfo.setUserDbKey(userDbKey);
            loginInfo.setExpireTimeMillis(expireTimeMillis);
            loginInfo.setRequest(request);
            LoginContextHolder.set(loginInfo);
            //切换数据源
            DynamicDataSourceContextHolder.push(userDbKey);

            //判断账号是否已禁用
//            Boolean disabled = sysUserService.checkIsDisabled(userId);
//            if(disabled){
//                //账号已禁用或者删除
//                response.setContentType("application/json;charset=UTF-8");
//                R<Object> result = R.fail(ReturnCode.RC405.getCode(), ReturnCode.RC405.getMsg());
//                String strResult = JSONObject.toJSONString(result);
//                response.getWriter().write(strResult);
//                return;
//            }

        }else if(requestURI.equals("/api/modules/sysUser/login") || requestURI.equals("/api/modules/sysUser2/login")){
            //如果是登录接口，从其他项目获取该用户的db_key,此处先写hee_erp
            DynamicDataSourceContextHolder.push("hee_erp");
        }

        LoginInfo loginInfo = LoginContextHolder.get();
        //检查token是否快过期
        if(loginInfo != null){
            //如果过期时间-当前时间小于30分钟，则重新生存token,自动续期
            long millisDiff = loginInfo.getExpireTimeMillis() - System.currentTimeMillis();
            if(millisDiff < 1000 * 60 * 30){
                String newToken = JwtUtil.createToken(loginInfo.getUserId(), loginInfo.getUserDbKey());
                response.setHeader(Const.RESPONSE_HEADER_TOKEN,newToken);
            }
        }

        chain.doFilter(request,response);
    }
}
